//-*-C++-*-
/***************************************************************************
 *
 *   Copyright (C) 2007 - 2023 by Willem van Straten
 *   Licensed under the Academic Free License version 2.1
 *
 ***************************************************************************/

// dspsr/Signal/General/dsp/DedispersionPipeConfig.h

#ifndef __dspsr_DedispersionPipeConfig_h
#define __dspsr_DedispersionPipeConfig_h

#include "dsp/DedispersionPipe.h"
#include "dsp/FilterbankConfig.h"
#include "dsp/InverseFilterbankConfig.h"
#include "CommandLine.h"

namespace dsp {

  //! Configuration parameters that describe the dedispersion section of a pipeline
  class DedispersionPipe::Config : public Reference::Able
  {

  public:

    //! Add options to the command-line menu
    void add_options (CommandLine::Menu& menu);

    //! Set the FFT length for dspsr -x
    void set_fft_length(const std::string& fft_length);

    //! Return true if convolution is enabled
    bool convolution_enabled() const;

    //! Return true if the (convolving) filterbank is enabled
    bool filterbank_enabled() const;
    
    //! Return true if the inverse filterbank is enabled
    bool inverse_filterbank_enabled() const;

    // perform coherent dedispersion
    bool coherent_dedispersion = true;

    // perform coherent derotation
    bool coherent_derotation = false;

    // remove inter-channel dispersion delays
    bool interchan_dedispersion = false;

    //! dispersion measure used in coherent dedispersion
    /*! zero is used to disable dedispersion; so initialize -1.0 */
    double dispersion_measure = -1.0;

    // rotation measure used in coherent derotation
    double rotation_measure = 0.0;

    // zap RFI during convolution
    bool zap_rfi = false;

    // use FFT benchmarks to choose an optimal FFT length
    bool use_fft_bench = false;

    // perform phase-coherent matrix convolution (calibration)
    std::string calibrator_database_filename;

    // set fft lengths and convolution edge effect lengths
    unsigned nsmear = 0;
    unsigned times_minimum_nfft = 0;

    // Filterbank configuration options
    Filterbank::Config filterbank;

    // Inverse Filterbank configuration options
    InverseFilterbank::Config inverse_filterbank;
    
    // Time-domain window applied in Convolution, Filterbank or InverseFilterbank
    std::string temporal_apodization_type;
    std::string spectral_apodization_type;

    // whether or not to apply deripple correction
    bool do_deripple = false;

    //! Return when convolution is performed: before, during, or after (Inverse)Filterbank
    dsp::Filterbank::Config::When get_convolve_when() const;

    //! return the number of channels produced by (Inverse)Filterbank 
    unsigned get_filterbank_nchan () const;

    //! Run signal processing algorithms on the GPU
    bool run_on_gpu = false;

    //! Print information about filter lengths
    bool report_vitals = false;

    //! Integrate the passband
    bool integrate_passband = false;

    //! Kludge to help DedispersionPipe::config match convolution_block_constraints template
    bool input_buffering = true;
  };
}

#include "dsp/convolution_block_constraints.h"
#include "dsp/PlasmaResponse.h"

template<class CompositePipeline>
void dsp::DedispersionPipe::prepare(CompositePipeline* composite)
{
  std::string app = composite->get_configuration()->application_name;

  if (Operation::verbose)
    std::cerr << "DedispersionPipe::prepare report=" << this->config->report_vitals << std::endl;

  if (this->kernel && this->config->report_vitals)
  {
    if (Operation::verbose)
      std::cerr << "DedispersionPipe::prepare kernel=" << (void*) this->kernel << std::endl;

    std::cerr << app  << ": dedispersion filter length=" << this->kernel->get_ndat()
        << " (minimum=" << this->kernel->get_minimum_ndat() << ")"
        << " complex samples" << std::endl;
  }

  convolution_block_constraints(composite, this->config.get(), app, this->config->report_vitals);
}

#endif
